import { useState } from "react"

const UseStateDemo = () => {
  // 基础状态示例
  const [count, setCount] = useState(0)

  // 对象状态示例
  const [user, setUser] = useState({
    name: "张三",
    age: 25,
  })

  // 懒初始化示例
  const [expensiveValue, setExpensiveValue] = useState(() => {
    console.log("懒初始化只在组件首次渲染时执行一次")
    return Math.random() * 100
  })

  // 异步更新批处理示例
  const handleMultipleUpdates = () => {
    // 在React 18之前，这些更新在事件处理函数中会被批处理，只触发一次渲染
    // 在React 18中，所有更新无论在哪里都会被自动批处理
    setCount(count + 1)
    setCount(count + 1)
    setCount(count + 1)
    // 最终count只会加1，而不是加3，因为每次都是基于相同的旧值更新
  }

  // 使用函数式更新来解决上面的问题
  const handleFunctionalUpdates = () => {
    setCount((prevCount) => prevCount + 1)
    setCount((prevCount) => prevCount + 1)
    setCount((prevCount) => prevCount + 1)
    // 最终count会加3，因为每次更新基于最新的状态值
  }

  // 对象更新需要保留旧的属性
  const updateUserName = () => {
    // 错误方式: 这会丢失age属性
    // setUser({ name: "李四" })

    // 正确方式: 使用展开运算符保留其他属性
    setUser({ ...user, name: "李四" })
  }

  const resetUser = () => {
    setUser({
      name: "张三",
      age: 25,
    })
  }

  return (
    <div className="demo-section">
      <h2>useState Hook 面试题讲解</h2>

      <div className="card">
        <h3>1. 基础用法</h3>
        <p>useState 是最基础的 Hook，用于在函数组件中添加状态：</p>
        <div className="code-example">
          <code>const [count, setCount] = useState(0)</code>
        </div>

        <p>
          当前计数: <strong>{count}</strong>
        </p>
        <button onClick={() => setCount(count + 1)}>增加</button>
        <button onClick={() => setCount(count - 1)}>减少</button>
        <button onClick={() => setCount(0)}>重置</button>
      </div>

      <div className="card">
        <h3>2. 常见面试问题: useState 更新是同步还是异步的?</h3>
        <p>
          在 React 中，useState 的更新是
          <span className="highlight">异步的</span>。当你调用 setState 后，React
          不会立即更新状态，
          而是将更新放入队列中，稍后批量处理，这种机制被称为"批处理"。
        </p>
        <div className="example-output">
          <p>点击下面的按钮会调用 setCount(count + 1) 三次，但计数只会增加1</p>
          <button onClick={handleMultipleUpdates}>多次更新 (只加1)</button>
        </div>

        <h3>解决方案: 函数式更新</h3>
        <p>
          如果新状态依赖于旧状态，应该传递一个函数给
          setState，该函数接收旧状态作为参数，返回新状态：
        </p>
        <div className="code-example">
          <code>setCount(prevCount =&gt; prevCount + 1)</code>
        </div>
        <div className="example-output">
          <p>
            点击下面的按钮会调用 setCount(prevCount =&gt; prevCount + 1)
            三次，计数会增加3
          </p>
          <button onClick={handleFunctionalUpdates}>函数式更新 (加3)</button>
        </div>
      </div>

      <div className="card">
        <h3>3. 常见面试问题: 如何正确地更新对象状态?</h3>
        <p>
          当状态是对象或数组时，useState
          不会自动合并更新，需要手动保留未更改的部分。
        </p>
        <div className="example-output">
          <p>
            当前用户: 姓名 - <strong>{user.name}</strong>, 年龄 -{" "}
            <strong>{user.age}</strong>
          </p>
          <button onClick={updateUserName}>更新姓名</button>
          <button onClick={resetUser}>重置用户</button>
        </div>
        <div className="code-example">
          <p>错误方式 (会丢失其他属性):</p>
          <code>setUser({"{ name: '李四' }"})</code>
          <p>正确方式 (保留其他属性):</p>
          <code>setUser({"{ ...user, name: '李四' }"})</code>
        </div>
      </div>

      <div className="card">
        <h3>4. 常见面试问题: 什么是懒初始化?</h3>
        <p>
          如果初始状态需要通过复杂计算获得，可以传递一个函数给
          useState，该函数只会在组件首次渲染时执行一次：
        </p>
        <div className="code-example">
          <code>
            const [value, setValue] = useState(() =&gt; {"{"}
            // 复杂计算 return computedValue;
            {"}"})
          </code>
        </div>
        <div className="example-output">
          <p>
            使用懒初始化的值: <strong>{expensiveValue.toFixed(2)}</strong>
          </p>
          <button onClick={() => setExpensiveValue(Math.random() * 100)}>
            生成新值
          </button>
        </div>
      </div>

      <div className="card">
        <h3>5. useState 面试核心要点</h3>
        <ul>
          <li>
            useState 不会自动合并对象，需要手动使用展开运算符保留之前的属性
          </li>
          <li>
            useState 的更新是异步的，如果新状态依赖旧状态，应使用函数式更新
          </li>
          <li>
            React 18
            引入了自动批处理，所有的状态更新都会被批处理，而不仅限于事件处理函数内
          </li>
          <li>useState 的初始值只在组件首次渲染时使用，后续渲染会被忽略</li>
          <li>
            当更新状态时，如果新值与当前值相同（使用 Object.is 比较），React
            将跳过重新渲染
          </li>
        </ul>
      </div>
    </div>
  )
}

export default UseStateDemo
